package com.icode.web.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * User: alexz
 * Date: 14-11-10
 * Time: 下午5:48
 */
public class ResponseRewriteFilter extends ServletFilterAdapter {
    private static final List<RewriteStrategy> REWRITE_STRATEGIES = new ArrayList<>();
    private static final List<String> EXCLUDE_RESOURCES = new ArrayList<>();

    static {
        REWRITE_STRATEGIES.add(new RewriteHtmlPageStrategy());

        EXCLUDE_RESOURCES.add(".gif");
        EXCLUDE_RESOURCES.add(".jpg");
        EXCLUDE_RESOURCES.add(".css");
        EXCLUDE_RESOURCES.add(".js");
        EXCLUDE_RESOURCES.add(".png");
        EXCLUDE_RESOURCES.add(".bmp");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String requestURI = httpServletRequest.getRequestURI();
        if (isExcludeResources(requestURI)) {
            chain.doFilter(request, response);
        } else {
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
            RewriteResponseWrapper rewriteResponseWrapper = new RewriteResponseWrapper(httpServletResponse);
            chain.doFilter(request, rewriteResponseWrapper);

            String result = rewriteResponseWrapper.getResult();
            for (RewriteStrategy rewriteStrategy : REWRITE_STRATEGIES) {
                if (rewriteStrategy.support(response, result)) {
                    result = rewriteStrategy.rewrite(result);
                }
            }

            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.println(result);
            outputStream.flush();
            outputStream.close();
        }
    }

    private boolean isExcludeResources(String requestURI) {
        for (String excludeResource : EXCLUDE_RESOURCES) {
            if (requestURI.contains(excludeResource)) {
                return true;
            }
        }
        return false;
    }

    public class RewriteResponseWrapper extends HttpServletResponseWrapper {
        private PrintWriter printWriter;
        private CharArrayWriter charArrayWriter;

        /**
         * Constructs a response adaptor wrapping the given response.
         *
         * @throws IllegalArgumentException if the response is null
         */
        public RewriteResponseWrapper(HttpServletResponse response) {
            super(response);
            this.charArrayWriter = new CharArrayWriter();
            this.printWriter = new PrintWriter(this.charArrayWriter);
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            return this.printWriter;
        }

        public String getResult() {
            return charArrayWriter.toString();
        }
    }
}
